package top.malaoshi.data;

import java.util.*;

public class GroupByAgg {

    protected DataTable dataTable;

    private boolean count = false;
    private List<GroupBy.Result> groupByResult;
    private String[] groupByColumns;
    protected List<String> maxColumns;
    protected List<String> minColumns;
    protected List<String> sumColumns;
    protected List<String> avgColumns;
    public GroupByAgg(DataTable dataTable,String[] groupByColumns,List<GroupBy.Result> datas){
        this.dataTable = dataTable;
        this.groupByResult = datas;
        this.groupByColumns = groupByColumns;
    }

    public GroupByAgg count(){
        count = true;
        return this;
    }
    public GroupByAgg max(String column){
        if(column == null || "".equals(column)){
            throw new IllegalArgumentException("max()函数需要传入列名");
        }
        if(maxColumns==null) {
            maxColumns = new ArrayList<>();
        }
        maxColumns.add(column);
        return this;
    }
    public GroupByAgg min(String column){
        if(column == null || "".equals(column)){
            throw new IllegalArgumentException("min()函数需要传入列名");
        }
        if(minColumns==null) {
            minColumns = new ArrayList<>();
        }
        minColumns.add(column);
        return this;
    }
    public GroupByAgg avg(String column){
        if(column == null || "".equals(column)){
            throw new IllegalArgumentException("avg()函数需要传入列名");
        }
        if(avgColumns==null) {
            avgColumns = new ArrayList<>();
        }
        avgColumns.add(column);
        return this;
    }
    public GroupByAgg sum(String column){
        if(column == null || "".equals(column)){
            throw new IllegalArgumentException("sum()函数需要传入列名");
        }
        if(sumColumns==null) {
            sumColumns = new ArrayList<>();
        }
        sumColumns.add(column);
        return this;
    }


    /**
     * 获取结果
     * @return
     */
    public DataTable getResult(){

        DataTable retTable = new DataTable();
        // 添加分组列
        for(String groupByColumn : groupByColumns){
            DataColumn dataColumn = dataTable.columns().get(groupByColumn);
            retTable.columns().add(dataColumn.getName(),dataColumn.getType());
        }

        // 添加分组数据
        for (GroupBy.Result item : groupByResult) {
            retTable.rows().add(item.getColumns().toArray());
        }


        count(retTable);
        max(retTable);
        min(retTable);
        sum(retTable);
        avg(retTable);
        return retTable;
    }

    private void count(DataTable tempTable){
        if(count) {
            String newColumn = "count";
            // 如果执行count，就添加 count 列
            tempTable.columns().add(newColumn, DataColumn.Type.INT);
            // 遍历groupby结果，计算总数，再添加table对应的记录中
            for (int i = 0,count=groupByResult.size();i< count;i++) {

                GroupBy.Result item = groupByResult.get(i);

                tempTable.rows().get(i).setValue(newColumn,item.getDataRows().size());

            }
        }
    }
    /**
     * 计算取最大值
     * @param tempTable
     */
    private void max(DataTable tempTable){
        if(maxColumns!=null){
            // 遍历max字段
            for(String column : maxColumns){
                // 向表中添加列
                String newColumn = "max("+column+")";
                DataColumn.Type type = dataTable.columns().get(column).getType();
                // 如果执行count，就添加 count 列
                tempTable.columns().add(newColumn, type);

                // 遍历groupby结果，对该列取最大值
                for (int i = 0,count=groupByResult.size();i< count;i++) {

                    GroupBy.Result item = groupByResult.get(i);
                    DataRow dr = Collections.max(item.getDataRows(), new ComparatorImpl(dataTable,column));
                    tempTable.rows().get(i).setValue(newColumn,dr.getValue(column));
                }
            }
        }
    }
    /**
     * 计算取最大值
     * @param tempTable
     */
    private void min(DataTable tempTable){
        if(minColumns!=null){
            // 遍历max字段
            for(String column : minColumns){
                // 向表中添加列
                String newColumn = "min("+column+")";
                DataColumn.Type type = dataTable.columns().get(column).getType();
                // 如果执行count，就添加 count 列
                tempTable.columns().add(newColumn, type);

                // 遍历groupby结果，对该列取最大值
                for (int i = 0,count=groupByResult.size();i< count;i++) {

                    GroupBy.Result item = groupByResult.get(i);
                    DataRow dr = Collections.min(item.getDataRows(), new ComparatorImpl(dataTable,column));
                    tempTable.rows().get(i).setValue(newColumn,dr.getValue(column));
                }
            }
        }
    }
    /**
     * 计算取最大值
     * @param tempTable
     */
    private void sum(DataTable tempTable){
        if(sumColumns!=null){
            // 遍历 sum 字段
            for(String column : sumColumns){
                // 向表中添加列
                String newColumn = "sum("+column+")";
                DataColumn.Type type = dataTable.columns().get(column).getType();
                // 添加 sum 列
                tempTable.columns().add(newColumn, type);

                // 遍历groupby结果，对该列取最大值
                for (int i = 0,count=groupByResult.size();i< count;i++) {

                    GroupBy.Result item = groupByResult.get(i);

                    if(type == DataColumn.Type.INT) {
                        int sum = 0;
                        for (DataRow dataRow : item.getDataRows()) {
                            Integer v = dataRow.getIntValue(column);
                            if(v!=null) {
                                sum += v;
                            }
                        }
                        tempTable.rows().get(i).setValue(newColumn,sum);
                    }else if(type == DataColumn.Type.DOUBLE) {
                        double sum = 0;
                        for (DataRow dataRow : item.getDataRows()) {
                            Double v = dataRow.getDoubleValue(column);
                            if(v!=null) {
                                sum += v;
                            }
                        }
                        tempTable.rows().get(i).setValue(newColumn,sum);
                    }
                }
            }
        }
    }

    private void avg(DataTable tempTable){
        if(avgColumns!=null){
            // 遍历 avg 字段
            for(String column : avgColumns){
                // 向表中添加列
                String newColumn = "avg("+column+")";
                DataColumn.Type type = dataTable.columns().get(column).getType();
                // 添加 avg 列
                tempTable.columns().add(newColumn, DataColumn.Type.DOUBLE);

                // 遍历groupby结果，对该列取最大值
                for (int i = 0,count=groupByResult.size();i< count;i++) {

                    GroupBy.Result item = groupByResult.get(i);

                    int countRow = item.getDataRows().size();

                    if(type == DataColumn.Type.INT) {
                        double sum = 0;
                        for (DataRow dataRow : item.getDataRows()) {
                            Integer v = dataRow.getIntValue(column);
                            if(v!=null) {
                                sum += v;
                            }
                        }
                        tempTable.rows().get(i).setValue(newColumn,sum/countRow);
                    }else if(type == DataColumn.Type.DOUBLE) {
                        double sum = 0;
                        for (DataRow dataRow : item.getDataRows()) {
                            Double v = dataRow.getDoubleValue(column);
                            if(v!=null) {
                                sum += v;
                            }
                        }
                        tempTable.rows().get(i).setValue(newColumn,sum/countRow);
                    }
                }
            }
        }
    }
    /**
     * 求最大值、最小值时用到的排序
     */
    public class ComparatorImpl implements Comparator<DataRow>{
        private DataTable dataTable;
        private String column;
        ComparatorImpl(DataTable dataTable,String column){
            this.dataTable = dataTable;
            this.column = column;
        }
        @Override
        public int compare(DataRow r1, DataRow r2) {
            int i = dataTable.columns().getIndex(column);
            DataColumn dataColumn = dataTable.columns().get(column);
            if(dataColumn.getType() == DataColumn.Type.INT ){
                Integer o1 = r1.getIntValue(i);
                Integer o2 = r2.getIntValue(i);

                if(o1==null && o2!=null){
                    return -1;
                }else if(o1!=null && o2==null){
                    return 1;
                }else if(o1==null && o2==null){
//                    return new ComparatorImpl(dataTable,columns,index+1).compare(r1,r2);
                    return 0;
                }else {
                    int res = o1 - o2;
                    if(res == 0){
//                        return new ComparatorImpl(dataTable,columns,index+1).compare(r1,r2);
                        return 0;
                    }else{
                        return res;
                    }
                }

            }else if(dataColumn.getType() == DataColumn.Type.DOUBLE){
                Double o1 = r1.getDoubleValue(i);
                Double o2 = r2.getDoubleValue(i);

                if(o1==null && o2!=null){
                    return -1;
                }else if(o1!=null && o2==null){
                    return 1;
                }else if(o1==null && o2==null){
//                    return new GroupBy.ComparatorImpl(dataTable,columns,index+1).compare(r1,r2);
                    return 0;
                }else {
                    if(o1 < o2) {
                        return -1;
                    }else if(o1 == o2){
//                        return new GroupBy.ComparatorImpl(dataTable,columns,index+1).compare(r1,r2);
                        return 0;
                    }else{
                        return 1;
                    }
                }

            }else if(dataColumn.getType() == DataColumn.Type.TEXT){
                String o1 = r1.getStringValue(i);
                String o2 = r2.getStringValue(i);

                if(o1==null && o2!=null){
                    return -1;
                }else if(o1!=null && o2==null){
                    return 1;
                }else if(o1==null && o2==null){
                    return 0;
//                    return new GroupBy.ComparatorImpl(dataTable,columns,index+1).compare(r1,r2);
                }else {
                    int res = o1.compareTo(o2);

                    if(res == 0){
//                        return new GroupBy.ComparatorImpl(dataTable,columns,index+1).compare(r1,r2);
                        return 0;
                    }else{
                        return res;
                    }
                }

            }else{
                throw new DataColumnTypeNotSupportedException(column,dataColumn.getType(),"不支持此操作！");
            }


        }
    }
    /**
     * 聚合函数结果
     */
    public class Result {
        private List<Object> columns = new ArrayList<>();
        private List<Object> datas = new ArrayList<>();

        public void addColumn(Object key){
            columns.add(key);
        }
        public List<Object> getColumns(){
            return columns;
        }
        public void addValue(Object o){
            datas.add(o);
        }

        public List<Object> getDatas() {
            return datas;
        }
    }
}
